<template>
  <el-card shadow="always" :body-style="{ padding: '20px' }">
    <el-form label-width="80px">
      <el-form-item label="SPU名称">
        <el-input placeholder="SPU名称" v-model="spuInfo.spuName"></el-input>
      </el-form-item>
      <el-form-item label="品牌">
        <el-select placeholder="请选择" v-model="spuInfo.tmId as number ">
          <el-option
            :label="item.tmName"
            :value="item.id as number"
            v-for="item in trademarkList"
            :key="item.id"
          >
          </el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="SPU描述">
        <el-input
          type="textarea"
          placeholder="请输入描述信息"
          v-model="spuInfo.description"
        ></el-input>
      </el-form-item>
      <el-form-item label="SPU图片">
        <el-upload
          v-model:file-list="fileList"
          :action="`${baseUrl}/admin/product/upload`"
          list-type="picture-card"
          :on-success="handlePicSuccess"
        >
          <el-icon><ele-Plus /></el-icon>
        </el-upload>
      </el-form-item>
      <el-form-item label="销售属性">
        <el-select placeholder="请选择销售属性" v-model="saleAttrSelect">
          <el-option
            :label="item.name"
            :value="`${item.id}:${item.name}`"
            v-for="item in unSelectSaleAttr"
            :key="item.id"
          >
          </el-option>
        </el-select>
        <el-button
          type="primary"
          size="default"
          @click="addSaleAttr"
          icon="ele-Plus"
          >添加销售属性</el-button
        >
      </el-form-item>
      <el-form-item>
        <el-table border stripe :data="saleAttrSelectList">
          <el-table-column type="index" width="80" label="序号" />
          <el-table-column
            label="属性名"
            width="100"
            prop="saleAttrName"
          ></el-table-column>
          <el-table-column label="属性值名称列表">
            <template v-slot="{ row }">
              <!-- 遍历当前row的属性值列表生成tag -->
              <el-tag
                v-for="(item, index) in row.spuSaleAttrValueList"
                :key="item.saleAttrValueName"
                type="danger"
                size="small"
                closable
                @close="closeTag(row.spuSaleAttrValueList, index)"
                >{{ item.saleAttrValueName }}</el-tag
              >
              <!-- input和button条件渲染 -->
              <el-input
                v-if="row.isEdit"
                placeholder=""
                size="small"
                @blur="toLook(row)"
                v-model="row.inputValue"
                ref="inputRef"
              ></el-input>
              <el-button
                v-else
                type="primary"
                size="small"
                icon="ele-Plus"
                @click="toEdit(row)"
                >添加销售属性值</el-button
              >
            </template>
          </el-table-column>
          <el-table-column label="操作" width="80">
            <template v-slot="{ $index }">
              <el-button
                type="danger"
                size="small"
                icon="ele-Delete"
                @click="deleteSaleAttr($index)"
              ></el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" size="default" @click="save">保存</el-button>
        <el-button size="default" @click="cancel">取消</el-button>
      </el-form-item>
    </el-form>
  </el-card>
</template>

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  name: "SpuInfo",
});
</script>

<script setup lang="ts">
import { ElMessage, type UploadUserFile } from "element-plus";
import { computed, nextTick, onMounted, ref } from "vue";
import { cloneDeep } from "lodash";
import { storeToRefs } from "pinia";
import { reqAllTrademark, type trademarkListType } from "@/api/trademark";
import {
  reqAllSaleAttrList,
  type saleAttrListType,
  type spuInfoItemType,
  type spuSaleAttrItemType,
  type spuSaleAttrListType,
  type spuSaleAttrValueItemType,
  type spuSaleAttrValueListType,
  type spuImageListType,
  reqAddSpu,
  reqImageListBySpuId,
  reqSaleAttrBySpuId,
  reqUpdateSpu,
} from "@/api/spu";
import useCategoryStore from "@/stores/category";

const categortStore = useCategoryStore();

//从store中获取当前的category3Id
const { category3Id } = storeToRefs(categortStore);

const emits = defineEmits<{
  (event: "changeShowIndex", index: number): void;
}>();

//接受父组件传递过来的spuInfo数据(可能是新增时的初始化数据,也可能是修改时的回填数据)
const props = defineProps<{
  spuInfo: spuInfoItemType;
}>();

//收集公共请求前缀，从环境变量中读取
const baseUrl = import.meta.env.VITE_API_URL;
//定义数据用来收集图片上传的图片列表
const fileList = ref<UploadUserFile[]>([]);

//定义一个数据用来收集销售属性列表
const saleAttrSelectList = ref<spuSaleAttrListType>([]);

//定义一个数据 保存销售属性双向绑定的收集的字符串
const saleAttrSelect = ref("");

//初始化保存所有品牌的数据
const trademarkList = ref<trademarkListType>([]);
//初始化保存所有销售属性的数据
const saleAttrList = ref<saleAttrListType>([]);

//初始化数据保存编辑模式的input元素
const inputRef = ref();

//封装所有品牌的请求和所有销售属性的请求(供新增spu时获取完整选项列表的时候使用)
const getAllTrademark = async () => {
  const result = await reqAllTrademark();
  trademarkList.value = result;
};

const getAllSaleAttr = async () => {
  const result = await reqAllSaleAttrList();
  saleAttrList.value = result;
};

//封装修改时候需要的 根据spuid的图片列表和销售属性列表的请求
const getImageListBySpuId = async () => {
  const result = await reqImageListBySpuId(spuInfo.value.id as number);
  //回填数据 回填给fileList
  result.forEach((item) => {
    fileList.value.push({
      name: item.imgName,
      url: item.imgUrl,
    });
  });
};

const getSaleAttrListBySpuId = async () => {
  const result = await reqSaleAttrBySpuId(spuInfo.value.id as number);
  saleAttrSelectList.value = result;
};

//初始化发送请求
//如果是新增则发送两个请求:所有品牌和所有销售属性请求
//如果是修改则发送四个请求:所有品牌和所有销售属性请求和当前spuId的销售属性列表和当前spuId的图片列表
onMounted(() => {
  getAllTrademark();
  getAllSaleAttr();

  if (spuInfo.value.id) {
    getImageListBySpuId();
    getSaleAttrListBySpuId();
  }
});

//当前组件就不需要初始化spuInfo,而是接受来自父组件传递的props即可
//因为spuInfo和当前的模板经常数据绑定,为了不修改props,我们可以把props深拷贝一份,自己保存使用
const spuInfo = ref<spuInfoItemType>(cloneDeep(props.spuInfo));

//图片上传成功的回调函数
const handlePicSuccess = (response: any, b: any, c: any) => {
  //参数1：当前图片上传请求的响应
  //参数2：当前图片的详细信息
  //参数3：当前上传成功后，完整的图片列表的数组
  // console.log(response, b, c);
  fileList.value = c;
};

//添加销售属性的按钮事件回调函数
const addSaleAttr = () => {
  //判断当前销售属性下拉选框是否有收集，如果有收集才能添加销售属性
  if (!saleAttrSelect.value) return ElMessage.error("销售属性为空");
  //解构收集到的销售属性值
  const [baseSaleAttrId, saleAttrName] = saleAttrSelect.value.split(":");
  //把当前收集到的销售属性信息插入到 已收集的销售属性列表中
  saleAttrSelectList.value.push({
    baseSaleAttrId: +baseSaleAttrId, //解构出来是一个字符串,需要转为number
    saleAttrName,
    spuSaleAttrValueList: [],
    isEdit: false, //模式
    inputValue: "", //专门用来收集当前销售属性中 的 添加销售属性值时input的数据
  });

  //收集完成之后 清空收集的值
  saleAttrSelect.value = "";
};

//计算属性,计算全部销售属性中还有哪些销售属性没有被选中
const unSelectSaleAttr = computed(() => {
  //saleAttrList:完整的销售属性列表
  //saleAttrSelectList:已经收集到的销售属性列表
  //最后我们希望的结果是,删除完成的销售属性列表中 已经被收集到的值
  return saleAttrList.value.filter((saleAttr) => {
    //遍历每一个完整的值,判断每一个 是否有和已经选中的名称相同,如果有,则返回false,如果没有则返回true
    return !saleAttrSelectList.value.some((saleAttrSelect) => {
      return saleAttrSelect.saleAttrName === saleAttr.name;
    });
  });
});

//点击添加销售属性值按钮,切换编辑模式的事件回调函数
const toEdit = (row: spuSaleAttrItemType) => {
  row.isEdit = true;

  //自动获取焦点
  nextTick(() => {
    inputRef.value.focus();
  });
};

//当添加销售属性值的input框失去焦点的时候，切换查看模式的事件回调函数
const toLook = (row: spuSaleAttrItemType) => {
  //首先切换到查看模式
  row.isEdit = false;

  //判断用户输入的inputvalue是否为空
  if (!row.inputValue) {
    return ElMessage.error("新增的销售属性值名称是空");
  }

  //判断输入的内容是否重复
  const isRepeat = row.spuSaleAttrValueList.some((item) => {
    return item.saleAttrValueName === row.inputValue;
  });

  if (isRepeat) {
    //清空inputValue的数据
    row.inputValue = "";
    return ElMessage.error("新增的销售属性值名称重复");
  }

  //把当前输入的内容整理一下,向当前row中添加新的销售属性值数据
  row.spuSaleAttrValueList.push({
    baseSaleAttrId: row.baseSaleAttrId, //当前spu销售属性的id
    saleAttrName: row.saleAttrName, //当前销售属性值所在的销售属性名称
    saleAttrValueName: row.inputValue as string, // 当前spu销售属性值的名字
  });

  //清空inputValue的数据
  row.inputValue = "";
};

//删除某一个tag
const closeTag = (list: spuSaleAttrValueListType, index: number) => {
  list.splice(index, 1);
};

//提交
const save = async () => {
  //整理参数1:图片列表
  //如果是修改的话 spuInfo的spuImageList值是null,无法使用push方法
  spuInfo.value.spuImageList = [];
  //因为修改的时候有回填数据,回填数据的格式和新上传数据的格式是不一致的,所以需要判断然后再整理参数
  fileList.value.forEach((item) => {
    /* if (item.response) {
      //response存在,说明是新上传的数据
      (spuInfo.value.spuImageList as spuImageListType).push({
        imgName: item.name,
        imgUrl: (item.response as any).data,
      });
    } else {
      //否则就是回填的数据
      (spuInfo.value.spuImageList as spuImageListType).push({
        imgName: item.name,
        imgUrl: item.url as string,
      });
    } */

    //也可以直接使用三元

    (spuInfo.value.spuImageList as spuImageListType).push({
      imgName: item.name,
      imgUrl: item.response
        ? (item.response as any).data
        : (item.url as string),
    });
  });

  //整理参数2：销售属性列表
  spuInfo.value.spuSaleAttrList = saleAttrSelectList.value;

  //提交的时候判断当前是新增还是修改(使用id判断)
  if (spuInfo.value.id) {
    await reqUpdateSpu(spuInfo.value);
  } else {
    await reqAddSpu(spuInfo.value);
  }

  //切换到spuList
  emits("changeShowIndex", 1);
};

const cancel = () => {
  //切换到spuList
  emits("changeShowIndex", 1);
};

//删除某个销售属性
const deleteSaleAttr = (index: number) => {
  saleAttrSelectList.value.splice(index, 1);
  ElMessage.success("删除销售属性成功")
};
</script>

<style scoped lang="scss"></style>
